package com.briup.pai.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.briup.pai.common.enums.DatasetStatusEnum;
import com.briup.pai.common.enums.ResultCodeEnum;
import com.briup.pai.common.enums.UploadStatusEnum;
import com.briup.pai.common.exception.BriupAssert;
import com.briup.pai.convert.FileInfoConvert;
import com.briup.pai.entity.dto.UploadChunkDTO;
import com.briup.pai.entity.dto.UploadVerifyFileDTO;
import com.briup.pai.entity.po.Dataset;
import com.briup.pai.entity.po.FileChunk;
import com.briup.pai.entity.po.FileInfo;
import com.briup.pai.entity.vo.UploadVerifyFileVO;
import com.briup.pai.service.IDatasetService;
import com.briup.pai.service.IFileChunkService;
import com.briup.pai.service.IFileInfoService;
import com.briup.pai.service.IUploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class UploadServiceImpl implements IUploadService {

    @Autowired
    @Lazy
    private IDatasetService datasetService;
    @Autowired
    private IFileInfoService fileInfoService;
    @Autowired
    private IFileChunkService fileChunkService;

    @Autowired
    private FileInfoConvert fileInfoConvert;

    @Value("${upload.nginx-file-path}")
    private String nginxFilePath;
    @Value("${upload.file-directory-name}")
    private String fileDirectoryName;

    @Override
    @Transactional
    public void modifyDatasetStatus(Integer datasetId, Integer status) {
        // 参数校验
        Dataset dataset = BriupAssert.requireNotNull(
                datasetService,
                Dataset::getId,
                datasetId,
                ResultCodeEnum.DATA_NOT_EXIST
        );
        BriupAssert.requireIn(
                status,
                DatasetStatusEnum.statusList(),
                ResultCodeEnum.PARAM_IS_ERROR);
        // 你要改的状态和原状态要不一样
        BriupAssert.requireNotEqual(
                dataset.getDatasetStatus(),
                status,
                ResultCodeEnum.DATASET_STATUS_ERROR
        );
        // 更新
        dataset.setDatasetStatus(status);
        datasetService.updateById(dataset);
    }

    @Override
    public UploadVerifyFileVO verifyFile(UploadVerifyFileDTO dto) {
        // 准备对象用于返回
        UploadVerifyFileVO uploadVerifyFileVO = new UploadVerifyFileVO();
        uploadVerifyFileVO.setUploaded(true);
        // 根据dto的hash查询看是否存在，如果存在就是上传过，如果不存在就是没有上传过
        LambdaQueryWrapper<FileInfo> lqw = new LambdaQueryWrapper<>();
        lqw.eq(FileInfo::getFileHash, dto.getFileHash());
        FileInfo fileInfo = fileInfoService.getOne(lqw);
        // 没有上传过
        if(ObjectUtil.isNull(fileInfo)){
            uploadVerifyFileVO.setUploaded(false);
            // 创建对应的文件夹
            String fileName = nginxFilePath+"/"+fileDirectoryName+"/"+dto.getFileHash();
            FileUtil.mkdir(fileName);
            // 将数据save到数据库里
            // 分片大小
            Long chunkSize = dto.getChunkSize();
            // 文件大小
            Long fileSize = dto.getFileSize();
            // 计算分片数量
            Long chunkNum = fileSize % chunkSize == 0 ? fileSize / chunkSize : fileSize / chunkSize + 1;
            FileInfo saveData = fileInfoConvert.uploadVerifyFileDTO2Po(dto);
            saveData.setFilePath(fileName+"/"+dto.getFileName());
            saveData.setChunkNum(chunkNum);
            saveData.setUploadStatus(UploadStatusEnum.INIT.getStatus());
            return uploadVerifyFileVO;
        }
        // 上传过但是没有上传完成
        if(ObjectUtil.notEqual(
                fileInfo.getUploadStatus(),
                UploadStatusEnum.UPLOADED.getStatus())){
            uploadVerifyFileVO.setUploaded(false);
            // 查询分片表中还没有上传完成的分片索引
            LambdaQueryWrapper<FileChunk> fclqw= new LambdaQueryWrapper<>();
            fclqw.eq(FileChunk::getFileHash, fileInfo.getFileHash());
            uploadVerifyFileVO.setUploadedChunks(
                    fileChunkService.list(fclqw).stream().map(FileChunk::getChunkIndex).toList());
            return uploadVerifyFileVO;
        }

        // 上传过，已完成（秒传）
        return uploadVerifyFileVO;
    }

    @Override
    public void uploadChunk(UploadChunkDTO dto) {

    }

    @Override
    public void modifyUploadStatus(String fileHash, Integer uploadStatus) {

    }

    @Override
    public void mergeChunks(String fileHash) {

    }

    @Override
    public void unzipDataset(Integer datasetId, String fileHash) {

    }

    @Override
    public void unzipClassify(Integer datasetId, Integer classifyId, String fileHash) {

    }
}